﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;

namespace Workflows.Components.TextMining.FullTextSearch
{
	/// <summary>
	/// 
	/// </summary>
	[Serializable]
	public class SqlFullTextSearchInstruction:InstructionBase
	{
		#region props
		private string _ConnStr;
		/// <summary></summary>
		public string ConnStr
		{
			get
			{
				return this._ConnStr;
			}
			set
			{
				this._ConnStr = value;
			}
		}

		private string _TableName;
		/// <summary></summary>
		public string TableName
		{
			get
			{
				return this._TableName;
			}
			set
			{
				this._TableName = value;
			}
		}

		private string _KeyField;
		/// <summary></summary>
		public string KeyField
		{
			get
			{
				return this._KeyField;
			}
			set
			{
				this._KeyField = value;
			}
		}

        private string _TitleField;
        /// <summary></summary>
        public string TitleField
        {
            get
            {
                return this._TitleField;
            }
            set
            {
                this._TitleField = value;
            }
        }

		private Dictionary<string,double> _TextFieldWeights;
		/// <summary></summary>
		public Dictionary<string, double> TextFieldWeights
		{
			get
			{
				return this._TextFieldWeights;
			}
			set
			{
				this._TextFieldWeights = value;
			}
		}

		private string _Query;
		/// <summary></summary>
		public string Query
		{
			get
			{
				return this._Query;
			}
			set
			{
				this._Query = value;
			}
		}

		private string _SearchResultFilePath;
		/// <summary></summary>
		public string SearchResultFilePath
		{
			get
			{
				return this._SearchResultFilePath;
			}
			set
			{
				this._SearchResultFilePath = value;
			}
		}

        private List<string> _IncludedTextFields;
        /// <summary></summary>
        public List<string> IncludedTextFields
        {
            get
            {
                return this._IncludedTextFields;
            }
            set
            {
                this._IncludedTextFields = value;
            }
        }
		#endregion

		#region ctor
		/// <summary>
		/// 
		/// </summary>
		public SqlFullTextSearchInstruction():base(Guid.Empty,Guid.Empty)
		{
			this._ConnStr = string.Empty;
			this._TableName = string.Empty;
			this._KeyField = string.Empty;
		    this._TitleField = string.Empty;
			this._TextFieldWeights=new Dictionary<string, double>();
			this._Query = string.Empty;
			this._SearchResultFilePath = string.Empty;
            this._IncludedTextFields=new List<string>();
		}

		/// <summary>
		/// constructor, all derived class must call default constructor to initialize
		/// default settings.
		/// </summary>
		public SqlFullTextSearchInstruction(Guid componentID, Guid jobTicketID,
			string connStr, string tblName, string keyField, string titleField,
			string query, string resultFilePath, 
			Dictionary<string,double> fieldWeights,
            List<string> includedTextFields) 
			: base(componentID, jobTicketID)
		{
			this._ConnStr = connStr;
			this._TableName = tblName;
			this._KeyField = keyField;
		    this._TitleField = titleField;
			this._Query = query;
			this._SearchResultFilePath = resultFilePath;
			this._TextFieldWeights = fieldWeights;
		    this._IncludedTextFields = includedTextFields;
		}
		#endregion

		#region Overrides of InstructionBase

		/// <summary>
		/// serialize settings to xml
		/// the function below is mainly for storing into database as serialized form instead of string
		/// </summary>
		public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
		{
			XmlNode xNode = XmlDataUtil.AddElement(ref xDoc, parentNode, "Instruction");
			XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Type", this.GetType().FullName);
			XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentID", this.OwnerComponentID.ToString());
			XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "WorkerID", this.OwnerWorkerInstanceID.ToString());
			XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SubmitTime", this.SubmitTime.ToString());
			XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "StartTime", this.StartTime.ToString());

			XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ConnStr", this.ConnStr);
			XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TableName", this.TableName);
			XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "KeyField", this.KeyField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode,"TitleField",this.TitleField);
			XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Query", this.Query);
			XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ResultFilePath", this.SearchResultFilePath);
			if (this.TextFieldWeights != null && this.TextFieldWeights.Count > 0)
			{
				XmlNode fieldNodes = XmlDataUtil.AddElement(ref xDoc, xNode, "Fields");
				foreach (string fieldName in this.TextFieldWeights.Keys)
				{
					XmlNode fieldNode = XmlDataUtil.AddElement(ref xDoc, fieldNodes, "Field");
					XmlDataUtil.UpdateAttribute(ref xDoc, fieldNode, "FieldName", fieldName);
					XmlDataUtil.UpdateAttribute(ref xDoc, fieldNode, "Weight",this.TextFieldWeights[fieldName].ToString());
				}
			}
            if(this.IncludedTextFields != null && this.IncludedTextFields.Count>0)
            {
                XmlNode txtFieldNodes = XmlDataUtil.AddElement(ref xDoc, xNode, "TextFields");
                foreach(string txtField in this.IncludedTextFields)
                {
                    XmlNode txtFieldNode = XmlDataUtil.AddElement(ref xDoc, txtFieldNodes, "TextField");
                    XmlDataUtil.UpdateAttribute(ref xDoc, txtFieldNode, "FieldName", txtField);
                }
            }

			return xNode;
		}

		/// <summary>
		/// instantiated from xml
		/// "&lt;Instructions&gt;&lt;Instruction&gt;&lt;/Instruction&gt;&lt;/Instruction&gt;", must
		/// instantiate from first child of root node
		/// </summary>
		public override InstructionBase Instantiate(XmlNode xNode)
		{
			if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
			{
				SqlFullTextSearchInstruction instruction = new SqlFullTextSearchInstruction();
				instruction.OwnerComponentID = new Guid(XmlDataUtil.GetAttributeValue(xNode, "ComponentID", Guid.NewGuid().ToString()));
				instruction.OwnerWorkerInstanceID = new Guid(XmlDataUtil.GetAttributeValue(xNode, "WorkerID", Guid.NewGuid().ToString()));
				instruction.SubmitTime = DateTime.Parse(XmlDataUtil.GetAttributeValue(xNode, "SubmitTime", TimeUtil.DbMinTime.ToString()));
				instruction.StartTime = DateTime.Parse(XmlDataUtil.GetAttributeValue(xNode, "StartTime", TimeUtil.DbMinTime.ToString()));

				instruction.ConnStr = XmlDataUtil.GetAttributeValue(xNode, "ConnStr", "");
				instruction.TableName = XmlDataUtil.GetAttributeValue(xNode, "TableName", "");
				instruction.KeyField = XmlDataUtil.GetAttributeValue(xNode, "KeyField", "");
			    instruction.TitleField = XmlDataUtil.GetAttributeValue(xNode, "TitleField", "");
				instruction.Query = XmlDataUtil.GetAttributeValue(xNode, "Query", "");
				instruction.SearchResultFilePath = XmlDataUtil.GetAttributeValue(xNode, "ResultFilePath", "");
				XmlNodeList fieldNodes = xNode.SelectNodes("Fields/Field");
				if (fieldNodes != null && fieldNodes.Count > 0)
				{
					instruction.TextFieldWeights = new Dictionary<string, double>();
					foreach (XmlNode fieldNode in fieldNodes)
					{
						string fieldName = XmlDataUtil.GetAttributeValue(fieldNode, "FieldName", "");
						double fieldWeight = double.Parse(XmlDataUtil.GetAttributeValue(fieldNode, "Weight", "0"));
						instruction.TextFieldWeights.Add(fieldName,fieldWeight);
					}
				}
			    XmlNodeList txtFieldNodes = xNode.SelectNodes("TextFields/TextField");
                if(txtFieldNodes !=null && txtFieldNodes.Count>0)
                {
                    instruction.IncludedTextFields=new List<string>();
                    foreach(XmlNode txtFieldNode in txtFieldNodes)
                    {
                        string txtFieldName = XmlDataUtil.GetAttributeValue(txtFieldNode, "FieldName", "");
                        instruction.IncludedTextFields.Add(txtFieldName);
                    }
                }

				return instruction;
			}
			else
			{
				throw new Exception("Unable to instantiate component: invalid type specified in xml node");
			}
		}

		#endregion
	}
}
